home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
051-060
/
amok53
/
oberon2.0
/
demos
/
tetriz.mod
< prev
next >
Wrap
Text File
|
1993-11-04
|
10KB
|
411 lines
MODULE Tetriz;
IMPORT I: Intuition,
g: Graphics,
e: Exec,
d: Dos,
au: Audio,
es: ExecSupport;
CONST
W = 10; (* Spielfeldgröße *)
H = 20;
bw = 20; (* Boxgröße *)
bh = 8;
w = bw*W; (* Fenstergröße *)
h = bh*H;
TYPE
LS = LONGSET; (* LONGSET = ARRAY 4,4 OF BOOLEAN *)
SteineFeld = ARRAY 7,4 OF LS;
CONST
S = SteineFeld(
LS{0..3}, LS{0,4,8,12}, LS{0..3}, LS{0,4,8,12},
LS{0..2,5}, LS{0,4,5,8}, LS{1,4..6}, LS{1,4,5,9},
LS{0..2,4}, LS{0,4,8,9}, LS{2,4..6}, LS{0,1,5,9},
LS{0..2,6}, LS{0,1,4,8}, LS{0,4..6}, LS{1,5,8,9},
LS{0,1,5,6}, LS{1,4,5,8}, LS{0,1,5,6}, LS{1,4,5,8},
LS{1,2,4,5}, LS{0,4,5,9}, LS{1,2,4,5}, LS{0,4,5,9},
LS{0,1,4,5}, LS{0,1,4,5}, LS{0,1,4,5}, LS{0,1,4,5});
VAR
Feld: ARRAY W,H OF INTEGER;
nw: I.NewWindow;
window: I.WindowPtr;
rp: g.RastPortPtr;
MyMsgPtr: I.IntuiMessagePtr;
MyMsg: I.IntuiMessage;
Lines: INTEGER;
HiScore: INTEGER;
CONST (* $DataChip+ *)
RectTable = "\x7F\x80";
RectTableSize = 2;
AllocationMap = "\x01\x08\x02\x04";
VAR
AllocPort: e.MsgPortPtr;
AllocIOB: au.IOAudioPtr;
AudioOpen: BOOLEAN;
AllocationMapPtr: POINTER TO ARRAY 4 OF CHAR;
RectTablePtr: POINTER TO ARRAY 2 OF CHAR;
TYPE
DoProc = PROCEDURE(x,y,c: INTEGER);
VAR
collCnt: INTEGER;
font: g.TextFontPtr;
fontName, winTitle: e.STRPTR;
attr: g.TextAttr;
(*-------------------------------------------------------------------------*)
(* $Debug- *)
PROCEDURE * Box(x,y,c: INTEGER);
BEGIN
IF (x>=0) AND (y>=0) THEN
g.SetAPen(rp,c);
x := x*bw; y := y*bh;
g.RectFill(rp,x+1,y+1,x+(bw-2),y+(bh-1));
END;
END Box;
PROCEDURE Do(s: LONGSET; x,y,c: INTEGER; what: DoProc);
VAR
i,j: INTEGER;
X,Y: INTEGER;
BEGIN
i := 0;
REPEAT
j := 0;
REPEAT
IF 4*i+j IN s THEN
X := x+j; Y := y+i;
CASE X OF 0..W-1: CASE Y OF 0..H-1: what(X,Y,c) ELSE END ELSE END;
END;
INC(j);
UNTIL j=4;
INC(i);
UNTIL i=4;
END Do;
PROCEDURE * CollCnt(x,y,c: INTEGER);
BEGIN IF Feld[x,y]=0 THEN INC(collCnt) END END CollCnt;
PROCEDURE Collide(s: LONGSET; x,y: INTEGER): BOOLEAN;
BEGIN
IF y<0 THEN RETURN FALSE END;
collCnt := 0;
Do(s,x,y,0,CollCnt);
RETURN collCnt#4;
END Collide;
PROCEDURE * AddIt(x,y,c: INTEGER);
BEGIN Feld[x,y] := c END AddIt;
PROCEDURE Draw(s: LONGSET; x,y,c: INTEGER);
BEGIN Do(s,x,y,c,Box) END Draw;
PROCEDURE WriteInt(i: INTEGER);
VAR
s: ARRAY 4 OF CHAR;
c: INTEGER;
BEGIN
c := 0;
REPEAT
s[3-c] := CHR(30H + i MOD 10);
i := i DIV 10;
INC(c);
UNTIL c=4;
g.SetAPen(rp,1); g.SetBPen(rp,0); g.SetDrMd(rp,g.jam2);
g.Text(rp,s,4);
END WriteInt;
PROCEDURE CheckLine();
VAR
x,y,y2: INTEGER;
lines: ARRAY H OF INTEGER;
lcnt: INTEGER;
BEGIN
lcnt := 0;
y := 0;
REPEAT
x := 0;
LOOP
IF Feld[x,y]=0 THEN EXIT END;
INC(x);
IF x=W THEN lines[lcnt] := 8*y; INC(lcnt); EXIT END;
END;
INC(y);
UNTIL y=H;
IF lcnt#0 THEN
INC(Lines,lcnt);
g.Move(rp,56,h+8); WriteInt(Lines);
es.BeginIO(AllocIOB);
g.SetDrMd(rp,SHORTSET{g.complement});
x := 0;
REPEAT
y := 0;
REPEAT
g.RectFill(rp,0,lines[y]+1,w-1,lines[y]+7);
INC(y);
UNTIL y=lcnt;
INC(x);
d.Delay(3);
UNTIL x=8;
g.SetDrMd(rp,g.jam1);
IF e.WaitIO(AllocIOB)=0 THEN END;
y := 19; y2 := 19; DEC(lcnt);
LOOP
IF y2<0 THEN EXIT END;
WHILE (lcnt>=0) AND (lines[lcnt]=8*y2) DO DEC(y2); DEC(lcnt) END;
IF y2<0 THEN EXIT END;
x := 0;
REPEAT
Feld[x,y] := Feld[x,y2];
INC(x);
UNTIL x=W;
DEC(y); DEC(y2);
END;
WHILE y>=0 DO
x := 0;
REPEAT
Feld[x,y] := 0;
INC(x);
UNTIL x=W;
DEC(y)
END;
y := 0;
REPEAT
x := 0;
REPEAT
Box(x,y,Feld[x,y]);
INC(x);
UNTIL x=W;
INC(y);
UNTIL y=H;
END;
END CheckLine;
(* $Debug= *)
PROCEDURE Play(): BOOLEAN; (* TRUE wenn Q gedrückt *)
VAR
Stein: INTEGER;
x,x2,y,y2,c: INTEGER;
TimeCnt: INTEGER;
Turn,NewTurn: INTEGER;
VHPosR[0DFF006H]: INTEGER;
BEGIN
g.SetAPen(rp,0);
g.RectFill(rp,0,0,w,h);
x := 0;
REPEAT
y := 0;
REPEAT
Feld[x,y] := 0;
INC(y);
UNTIL y=H;
INC(x);
UNTIL x=W;
Lines := 0; TimeCnt := 0;
REPEAT
Stein := VHPosR MOD 7; c := Stein MOD 3 + 1; Turn := 0;
x := W DIV 2 - 1; IF Stein=0 THEN DEC(x) END;
y := 0;
LOOP
IF Collide(S[Stein,Turn],x,y) THEN EXIT END;
Draw(S[Stein,Turn],x,y-1,0);
Draw(S[Stein,Turn],x,y,c);
LOOP
Draw(S[Stein,Turn],x,y,c);
IF TimeCnt>=300 THEN DEC(TimeCnt,300); EXIT END;
REPEAT
e.WaitPort(window.userPort);
MyMsgPtr := e.GetMsg(window.userPort);
UNTIL MyMsgPtr#NIL;
MyMsg := MyMsgPtr^;
e.ReplyMsg(MyMsgPtr);
IF I.intuiTicks IN MyMsg.class THEN INC(TimeCnt,30+Lines) END;
IF I.vanillaKey IN MyMsg.class THEN
Draw(S[Stein,Turn],x,y,0);
CASE MyMsg.code OF
ORD('4'):
IF (x>0) AND NOT Collide(S[Stein,Turn],x-1,y) THEN DEC(x) END |
ORD('5'):
NewTurn := (Turn + 1) MOD 4;
x2 := x; y2 := y;
IF Stein=0 THEN
IF ODD(Turn) THEN IF x2=0 THEN x2 := -1 ELSE DEC(x2); INC(y2) END
ELSE INC(x2); DEC(y2) END;
END;
IF NOT Collide(S[Stein,NewTurn],x2,y2) THEN
Turn := NewTurn;
x := x2;
y := y2;
END |
ORD('6'):
IF NOT Collide(S[Stein,Turn],x+1,y) THEN INC(x) END |
ORD(' '):
LOOP
Draw(S[Stein,Turn],x,y,c);
IF Collide(S[Stein,Turn],x,y+1) THEN EXIT END;
d.Delay(1);
INC(y);
Draw(S[Stein,Turn],x,y-1,0);
END;
EXIT |
ORD('q'): RETURN TRUE |
ELSE END;
END;
IF I.closeWindow IN MyMsg.class THEN RETURN TRUE END;
END;
INC(y);
END;
IF y>0 THEN
Do(S[Stein,Turn],x,y-1,c,AddIt);
CheckLine;
END;
UNTIL y=0;
IF Lines>HiScore THEN HiScore := Lines END;
d.Delay(30);
RETURN FALSE;
END Play;
(*-------------------------------------------------------------------------*)
BEGIN
window := NIL; HiScore := 0; AllocPort := NIL; AudioOpen := FALSE;
NEW(AllocationMapPtr); NEW(RectTablePtr); NEW(AllocIOB); NEW(winTitle); NEW(fontName);
IF (AllocationMapPtr=NIL) OR (RectTablePtr=NIL) OR (AllocIOB=NIL) OR
(winTitle=NIL) OR (fontName=NIL) THEN
HALT(20);
END;
(*------ Open Audio-Device: ------*)
AllocPort := es.CreatePort("",0);
IF AllocPort=NIL THEN HALT(0) END;
AllocIOB.request.message.node.pri := -40;
AllocIOB.request.message.replyPort := AllocPort;
AllocationMapPtr^ := AllocationMap;
AllocIOB.data := AllocationMapPtr;
AllocIOB.length := 4;
IF (e.OpenDevice("audio.device",0,AllocIOB,LONGSET{})#0) OR
(AllocIOB.request.error = au.allocFailed)
THEN HALT(0) END;
AudioOpen := TRUE;
AllocIOB.request.command := e.write;
AllocIOB.request.flags := SHORTSET{4};
RectTablePtr^ := RectTable;
AllocIOB.data := RectTablePtr;
AllocIOB.length := RectTableSize;
AllocIOB.period := 4000;
AllocIOB.cycles := 200;
AllocIOB.volume := 64;
(*------ Open Window: ------*)
nw.leftEdge := (g.gfx.normalDisplayColumns - (w+ 8)) DIV 2;
nw.topEdge := (g.gfx.normalDisplayRows - (h+24)) DIV 2;
nw.width := w+8;
nw.height := h+24;
nw.blockPen := 1;
nw.idcmpFlags := LONGSET{I.closeWindow,I.vanillaKey,I.intuiTicks};
nw.flags := LONGSET{I.windowClose,I.windowDepth,I.windowDrag,I.gimmeZeroZero,I.activate};
nw.type := {I.wbenchScreen};
winTitle^ := "Tetriz";
nw.title := winTitle;
IF I.int.libNode.version>=36 THEN
window := I.OpenWindowTags(nw,I.waInnerWidth, w,
I.waInnerHeight,h+10,
0 (* Utility.done *) );
ELSE
window := I.OpenWindow(nw);
END;
IF window=NIL THEN HALT(0) END;
rp := window.rPort;
fontName^ := "topaz.font";
attr.name := fontName;
attr.ySize := 8;
font := g.OpenFont(attr);
IF font=NIL THEN HALT(0) END;
g.SetFont(rp,font);
(*------ Start: ------*)
LOOP
g.SetAPen(rp,0); g.SetDrMd(rp,g.jam1);
g.RectFill(rp,0,0,w,h);
g.SetAPen(rp,1);
g.Move(rp, 20,20); g.Text(rp,"S = Start",9);
g.Move(rp, 20,40); g.Text(rp,"Q = Quit" ,8);
g.Move(rp, 20,60); g.Text(rp,"© 1989 by F. Siebert",20);
g.Move(rp, 20,80); g.Text(rp," AMOK Stuttgart",17);
g.Move(rp, 0,h+8); g.Text(rp,"Lines:" ,6);
g.Move(rp,108,h+8); g.Text(rp,"Hi:" ,3);
g.Move(rp,144,h+8); WriteInt(HiScore);
REPEAT
REPEAT
e.WaitPort(window.userPort);
MyMsgPtr := e.GetMsg(window.userPort);
UNTIL MyMsgPtr#NIL;
MyMsg := MyMsgPtr^;
e.ReplyMsg(MyMsgPtr);
UNTIL LONGSET{I.intuiTicks}#MyMsg.class;
IF I.vanillaKey IN MyMsg.class THEN
CASE MyMsg.code OF
ORD('s'): IF Play() THEN EXIT END |
ORD('q'): EXIT |
ELSE END;
ELSIF I.closeWindow IN MyMsg.class THEN
EXIT
END;
END;
CLOSE
IF window#NIL THEN I.CloseWindow(window) END;
IF AudioOpen THEN e.CloseDevice(AllocIOB) END;
IF AllocPort#NIL THEN es.DeletePort(AllocPort) END;
IF font#NIL THEN g.CloseFont(font) END;
END Tetriz.